/***************************************************************/
/*                                                             */
/*   LC-3b Simulator                                           */
/*                                                             */
/*   Name: Renato Oliveira                                     */
/*   UTEID : rad2735                                           */
/*   EE 460N                                                   */
/*   The University of Texas at Austin                         */
/*                                                             */
/***************************************************************/

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

/***************************************************************/
/*                                                             */
/* Files:  ucode        Microprogram file                      */
/*         pagetable    page table in LC-3b machine language   */
/*         isaprogram   LC-3b machine language program file    */
/*                                                             */
/***************************************************************/

/***************************************************************/
/* These are the functions you'll have to write.               */
/***************************************************************/

void eval_micro_sequencer();
void cycle_memory();
void eval_bus_drivers();
void drive_bus();
void latch_datapath_values();

/***************************************************************/
/* A couple of useful definitions.                             */
/***************************************************************/
#define FALSE 0
#define TRUE  1

/***************************************************************/
/* Use this to avoid overflowing 16 bits on the bus.           */
/***************************************************************/
#define Low16bits(x) ((x) & 0xFFFF)

/***************************************************************/
/* Definition of the control store layout.                     */
/***************************************************************/
#define CONTROL_STORE_ROWS 128
#define INITIAL_STATE_NUMBER 18

/***************************************************************/
/* Definition of bit order in control store word.              */
/***************************************************************/
enum CS_BITS {
    IRD1,IRD0,
    COND2, COND1, COND0,   /*New COND2 singal*/
    J6, J5, J4, J3, J2, J1, J0,
    LD_MAR,
    LD_MDR,
    LD_IR,
    LD_BEN,
    LD_REG,
    LD_CC,
    LD_PC,
    LD_Priv,
    LD_Prio,
    LD_SavedSSP,
    LD_SavedUSP,
    LD_Vector,
	LD_NextJ,
	LD_VA,
	LD_PTE,
    GATE_PC,
    GATE_MDR,
    GATE_ALU,
    GATE_MARMUX,
    GATE_Vector,
    GATE_PCmin2,
    GATE_PSR,
    GATE_SP,
    GATE_SHF,
	GATE_VA,
	GATE_PTE,
	GATE_PTBR,
    PCMUX1, PCMUX0,
    DRMUX1, DRMUX0,
    SR1MUX1, SR1MUX0,
    ADDR1MUX,
    ADDR2MUX1, ADDR2MUX0,
    SPMUX1, SPMUX0,
    MARMUX,
    VectorMUX2, VectorMUX1, VectorMUX0,
    PSRMUX,
    ALUK1, ALUK0,
    MIO_EN,
    R_W,
    Set_Priv,
    DATA_SIZE,
    LSHF1,
    /* MODIFY: you have to add all your new control signals */
    CONTROL_STORE_BITS
} CS_BITS;

/***************************************************************/
/* Functions to get at the control bits.                       */
/***************************************************************/
int GetIRD(int *x)           { return((x[IRD1]<<1)+x[IRD0]); }
int GetCOND(int *x)          { return((x[COND2] << 2) + (x[COND1] << 1) + (x[COND0])); } /*New COND2 singal*/
int GetJ(int *x)             { return((x[J6] << 6) + (x[J5] << 5) + (x[J4] << 4) + 
									  (x[J3] << 3) + (x[J2] << 2) +
									  (x[J1] << 1) + x[J0]);
}
int GetLD_MAR(int *x)        { return(x[LD_MAR]); }
int GetLD_MDR(int *x)        { return(x[LD_MDR]); }
int GetLD_IR(int *x)         { return(x[LD_IR]); }
int GetLD_BEN(int *x)        { return(x[LD_BEN]); }
int GetLD_REG(int *x)        { return(x[LD_REG]); }
int GetLD_CC(int *x)         { return(x[LD_CC]); }
int GetLD_PC(int *x)         { return(x[LD_PC]); }
int GetLD_Priv(int *x)       { return(x[LD_Priv]); }
int GetLD_Prio(int *x)       { return(x[LD_Prio]); }
int GetLD_SavSSP(int *x)     { return(x[LD_SavedSSP]); }
int GetLD_SavUSP(int *x)     { return(x[LD_SavedUSP]); }
int GetLD_Vector(int *x)     { return(x[LD_Vector]); }

int GetLD_NextJ(int *x)      { return(x[LD_NextJ]); }
int GetLD_VA(int *x)		 { return(x[LD_VA]); }
int GetLD_PTE(int *x)		 { return(x[LD_PTE]); }

int GetGATE_PC(int *x)       { return(x[GATE_PC]); }
int GetGATE_MDR(int *x)      { return(x[GATE_MDR]); }
int GetGATE_ALU(int *x)      { return(x[GATE_ALU]); }
int GetGATE_MARMUX(int *x)   { return(x[GATE_MARMUX]); }
int GetGATE_Vector(int *x)   { return(x[GATE_Vector]); }
int GetGATE_PCmin2(int *x)   { return(x[GATE_PCmin2]); }
int GetGATE_PSR(int *x)      { return(x[GATE_PSR]); }
int GetGATE_SP(int *x)       { return(x[GATE_SP]); }
int GetGATE_SHF(int *x)      { return(x[GATE_SHF]); }

int GetGATE_VA(int *x)       { return(x[GATE_VA]); }
int GetGATE_PTE(int *x)      { return(x[GATE_PTE]); }
int GetGATE_PTBR(int *x)     { return(x[GATE_PTBR]); }

int GetPCMUX(int *x)         { return((x[PCMUX1] << 1) + x[PCMUX0]); }
int GetDRMUX(int *x)         { return((x[DRMUX1] << 1) + x[DRMUX0]); }
int GetSR1MUX(int *x)        { return((x[SR1MUX1] << 1) + x[SR1MUX0]); }
int GetADDR1MUX(int *x)      { return(x[ADDR1MUX]); }
int GetADDR2MUX(int *x)      { return((x[ADDR2MUX1] << 1) + x[ADDR2MUX0]); }
int GetSPMUX(int *x)         { return((x[SPMUX1] << 1) + x[SPMUX0]); }
int GetMARMUX(int *x)        { return(x[MARMUX]); }
int GetVectorMUX(int *x)     { return((x[VectorMUX2] << 2)+ (x[VectorMUX1] << 1) + x[VectorMUX0]); }
int GetPSRMUX(int *x)        { return(x[PSRMUX]); }
int GetALUK(int *x)          { return((x[ALUK1] << 1) + x[ALUK0]); }
int GetMIO_EN(int *x)        { return(x[MIO_EN]); }
int GetR_W(int *x)           { return(x[R_W]); }
int GetSetPriv(int *x)       { return(x[Set_Priv]); }
int GetDATA_SIZE(int *x)     { return(x[DATA_SIZE]); }
int GetLSHF1(int *x)         { return(x[LSHF1]); }
/* MODIFY: you can add more Get functions for your new control signals */

/***************************************************************/
/* The control store rom.                                      */
/***************************************************************/
int CONTROL_STORE[CONTROL_STORE_ROWS][CONTROL_STORE_BITS];

/***************************************************************/
/* Main memory.                                                */
/***************************************************************/
/* MEMORY[A][0] stores the least significant byte of word at word address A
   MEMORY[A][1] stores the most significant byte of word at word address A
   There are two write enable signals, one for each byte. WE0 is used for
   the least significant byte of a word. WE1 is used for the most significant
   byte of a word. */

#define WORDS_IN_MEM    0x2000 /* 32 frames */ 
#define MEM_CYCLES      5
int MEMORY[WORDS_IN_MEM][2];

/***************************************************************/

/***************************************************************/

/***************************************************************/
/* LC-3b State info.                                           */
/***************************************************************/
#define LC_3b_REGS 8

int RUN_BIT;	/* run bit */
int BUS;	/* value of the bus */

typedef struct System_Latches_Struct{

    int PC,		  /* program counter */
        PSR,    /*processor status register*/
        MDR,	  /* memory data register */
        MAR,	  /* memory address register */
        IR,		  /* instruction register */
        N,		  /* n condition bit */
        Z,		  /* z condition bit */
        P,		  /* p condition bit */
        BEN;    /* ben register */

    int READY;	/* ready bit */
    /* The ready bit is also latched as you dont want the memory system to assert it
       at a bad point in the cycle*/

    int REGS[LC_3b_REGS]; /* register file. */

    int MICROINSTRUCTION[CONTROL_STORE_BITS]; /* The microintruction */

    int STATE_NUMBER; /* Current State Number - Provided for debugging */

    /* For lab 4 */
    int INTV; /* Interrupt vector register */
    int EXCV; /* Exception vector register */
    int SSP;  /* Initial value of system stack pointer */

    /* MODIFY: You may add system latches that are required by your implementation */
    int priority, /*Program priority*/
        Priv,     /*Program privilege level*/
        Vector,   /*register to store the vector address*/
        USP;      /*register to store the stack pointer stuf*/

    /* For lab 5 */
    int PTBR; /* This is initialized when we load the page table */
    int VA;   /* Temporary VA register */
    /* MODIFY: you should add here any other registers you need to implement virtual memory */
    int PTE;  /*other register to store the PTE being used*/
    int NextJ; /*register to remember previous next statet*/

} System_Latches;

/* Data Structure for Latch */

System_Latches CURRENT_LATCHES, NEXT_LATCHES;

/* For lab 5 */
#define PAGE_NUM_BITS 9
#define PTE_PFN_MASK 0x3E00
#define PTE_VALID_MASK 0x0004
#define PAGE_OFFSET_MASK 0x1FF

/***************************************************************/
/* A cycle counter.                                            */
/***************************************************************/
int CYCLE_COUNT;

/*interupt signal*/
int INT_SIG = 0;
int INT_PRIO = 1;

/***************************************************************/
/*                                                             */
/* Procedure : help                                            */
/*                                                             */
/* Purpose   : Print out a list of commands.                   */
/*                                                             */
/***************************************************************/
void help() {
    printf("----------------LC-3bSIM Help-------------------------\n");
    printf("go               -  run program to completion       \n");
    printf("run n            -  execute program for n cycles    \n");
    printf("mdump low high   -  dump memory from low to high    \n");
    printf("rdump            -  dump the register & bus values  \n");
    printf("?                -  display this help menu          \n");
    printf("quit             -  exit the program                \n\n");
}

/***************************************************************/
/*                                                             */
/* Procedure : cycle                                           */
/*                                                             */
/* Purpose   : Execute a cycle                                 */
/*                                                             */
/***************************************************************/
void cycle() {

    eval_micro_sequencer();
    cycle_memory();
    eval_bus_drivers();
    drive_bus();
    latch_datapath_values();

    CURRENT_LATCHES = NEXT_LATCHES;

    CYCLE_COUNT++;

    /*trigger interupt*/
    if (CYCLE_COUNT == 300)
        INT_SIG = 1;
}

/***************************************************************/
/*                                                             */
/* Procedure : run n                                           */
/*                                                             */
/* Purpose   : Simulate the LC-3b for n cycles.                 */
/*                                                             */
/***************************************************************/
void run(int num_cycles) {
    int i;

    if (RUN_BIT == FALSE) {
        printf("Can't simulate, Simulator is halted\n\n");
        return;
    }

    printf("Simulating for %d cycles...\n\n", num_cycles);
    for (i = 0; i < num_cycles; i++) {
        if (CURRENT_LATCHES.PC == 0x0000) {
            RUN_BIT = FALSE;
            printf("Simulator halted\n\n");
            break;
        }
        cycle();
    }
}

/***************************************************************/
/*                                                             */
/* Procedure : go                                              */
/*                                                             */
/* Purpose   : Simulate the LC-3b until HALTed.                 */
/*                                                             */
/***************************************************************/
void go() {
    if (RUN_BIT == FALSE) {
        printf("Can't simulate, Simulator is halted\n\n");
        return;
    }

    printf("Simulating...\n\n");
    while (CURRENT_LATCHES.PC != 0x0000)
        cycle();
    RUN_BIT = FALSE;
    printf("Simulator halted\n\n");
}

/***************************************************************/
/*                                                             */
/* Procedure : mdump                                           */
/*                                                             */
/* Purpose   : Dump a word-aligned region of memory to the     */
/*             output file.                                    */
/*                                                             */
/***************************************************************/
void mdump(FILE * dumpsim_file, int start, int stop) {
    int address; /* this is a byte address */

    printf("\nMemory content [0x%0.4x..0x%0.4x] :\n", start, stop);
    printf("-------------------------------------\n");
    for (address = (start >> 1); address <= (stop >> 1); address++)
        printf("  0x%0.4x (%d) : 0x%0.2x%0.2x\n", address << 1, address << 1, MEMORY[address][1], MEMORY[address][0]);
    printf("\n");

    /* dump the memory contents into the dumpsim file */
    fprintf(dumpsim_file, "\nMemory content [0x%0.4x..0x%0.4x] :\n", start, stop);
    fprintf(dumpsim_file, "-------------------------------------\n");
    for (address = (start >> 1); address <= (stop >> 1); address++)
        fprintf(dumpsim_file, " 0x%0.4x (%d) : 0x%0.2x%0.2x\n", address << 1, address << 1, MEMORY[address][1], MEMORY[address][0]);
    fprintf(dumpsim_file, "\n");
    fflush(dumpsim_file);
}

/***************************************************************/
/*                                                             */
/* Procedure : rdump                                           */
/*                                                             */
/* Purpose   : Dump current register and bus values to the     */
/*             output file.                                    */
/*                                                             */
/***************************************************************/
void rdump(FILE * dumpsim_file) {
    int k;

    printf("\nCurrent register/bus values :\n");
    printf("-------------------------------------\n");
    printf("Cycle Count  : %d\n", CYCLE_COUNT);
    printf("PC           : 0x%0.4x\n", CURRENT_LATCHES.PC);
    printf("IR           : 0x%0.4x\n", CURRENT_LATCHES.IR);
    printf("STATE_NUMBER : 0x%0.4x\n\n", CURRENT_LATCHES.STATE_NUMBER);
    printf("BUS          : 0x%0.4x\n", BUS);
    printf("MDR          : 0x%0.4x\n", CURRENT_LATCHES.MDR);
    printf("MAR          : 0x%0.4x\n", CURRENT_LATCHES.MAR);
    printf("CCs: N = %d  Z = %d  P = %d\n", CURRENT_LATCHES.N, CURRENT_LATCHES.Z, CURRENT_LATCHES.P);
    printf("Registers:\n");
    for (k = 0; k < LC_3b_REGS; k++)
        printf("%d: 0x%0.4x\n", k, CURRENT_LATCHES.REGS[k]);
    printf("\n");

    /* dump the state information into the dumpsim file */
    fprintf(dumpsim_file, "\nCurrent register/bus values :\n");
    fprintf(dumpsim_file, "-------------------------------------\n");
    fprintf(dumpsim_file, "Cycle Count  : %d\n", CYCLE_COUNT);
    fprintf(dumpsim_file, "PC           : 0x%0.4x\n", CURRENT_LATCHES.PC);
    fprintf(dumpsim_file, "IR           : 0x%0.4x\n", CURRENT_LATCHES.IR);
    fprintf(dumpsim_file, "STATE_NUMBER : 0x%0.4x\n\n", CURRENT_LATCHES.STATE_NUMBER);
    fprintf(dumpsim_file, "BUS          : 0x%0.4x\n", BUS);
    fprintf(dumpsim_file, "MDR          : 0x%0.4x\n", CURRENT_LATCHES.MDR);
    fprintf(dumpsim_file, "MAR          : 0x%0.4x\n", CURRENT_LATCHES.MAR);
    fprintf(dumpsim_file, "CCs: N = %d  Z = %d  P = %d\n", CURRENT_LATCHES.N, CURRENT_LATCHES.Z, CURRENT_LATCHES.P);
    fprintf(dumpsim_file, "Registers:\n");
    for (k = 0; k < LC_3b_REGS; k++)
        fprintf(dumpsim_file, "%d: 0x%0.4x\n", k, CURRENT_LATCHES.REGS[k]);
    fprintf(dumpsim_file, "\n");
    fflush(dumpsim_file);
}

/***************************************************************/
/*                                                             */
/* Procedure : get_command                                     */
/*                                                             */
/* Purpose   : Read a command from standard input.             */
/*                                                             */
/***************************************************************/
void get_command(FILE * dumpsim_file) {
    char buffer[20];
    int start, stop, cycles;

    printf("LC-3b-SIM> ");

    scanf("%s", buffer);
    printf("\n");

    switch (buffer[0]) {
    case 'G':
    case 'g':
        go();
        break;

    case 'M':
    case 'm':
        scanf("%i %i", &start, &stop);
        mdump(dumpsim_file, start, stop);
        break;

    case '?':
        help();
        break;
    case 'Q':
    case 'q':
        printf("Bye.\n");
        exit(0);

    case 'R':
    case 'r':
        if (buffer[1] == 'd' || buffer[1] == 'D')
            rdump(dumpsim_file);
        else {
            scanf("%d", &cycles);
            run(cycles);
        }
        break;

    default:
        printf("Invalid Command\n");
        break;
    }
}

/***************************************************************/
/*                                                             */
/* Procedure : init_control_store                              */
/*                                                             */
/* Purpose   : Load microprogram into control store ROM        */
/*                                                             */
/***************************************************************/
void init_control_store(char *ucode_filename) {
    FILE *ucode;
    int i, j, index;
    char line[200];

    printf("Loading Control Store from file: %s\n", ucode_filename);

    /* Open the micro-code file. */
    if ((ucode = fopen(ucode_filename, "r")) == NULL) {
        printf("Error: Can't open micro-code file %s\n", ucode_filename);
        exit(-1);
    }

    /* Read a line for each row in the control store. */
    for (i = 0; i < CONTROL_STORE_ROWS; i++) {
        if (fscanf(ucode, "%[^\n]\n", line) == EOF) {
            printf("Error: Too few lines (%d) in micro-code file: %s\n",
                i, ucode_filename);
            exit(-1);
        }

        /* Put in bits one at a time. */
        index = 0;

        for (j = 0; j < CONTROL_STORE_BITS; j++) {
            /* Needs to find enough bits in line. */
            if (line[index] == '\0') {
                printf("Error: Too few control bits in micro-code file: %s\nLine: %d\n",
                    ucode_filename, i);
                exit(-1);
            }
            if (line[index] != '0' && line[index] != '1') {
                printf("Error: Unknown value in micro-code file: %s\nLine: %d, Bit: %d\n",
                    ucode_filename, i, j);
                exit(-1);
            }

            /* Set the bit in the Control Store. */
            CONTROL_STORE[i][j] = (line[index] == '0') ? 0 : 1;
            index++;
        }

        /* Warn about extra bits in line. */
        if (line[index] != '\0')
            printf("Warning: Extra bit(s) in control store file %s. Line: %d\n",
            ucode_filename, i);
    }
    printf("\n");
}

/************************************************************/
/*                                                          */
/* Procedure : init_memory                                  */
/*                                                          */
/* Purpose   : Zero out the memory array                    */
/*                                                          */
/************************************************************/
void init_memory() {
    int i;

    for (i = 0; i < WORDS_IN_MEM; i++) {
        MEMORY[i][0] = 0;
        MEMORY[i][1] = 0;
    }
}

/**************************************************************/
/*                                                            */
/* Procedure : load_program                                   */
/*                                                            */
/* Purpose   : Load program and service routines into mem.    */
/*                                                            */
/**************************************************************/
void load_program(char *program_filename, int is_virtual_base) {
    FILE * prog;
    int ii, word, program_base, pte, virtual_pc;

    /* Open program file. */
    prog = fopen(program_filename, "r");
    if (prog == NULL) {
        printf("Error: Can't open program file %s\n", program_filename);
        exit(-1);
    }

    /* Read in the program. */
    if (fscanf(prog, "%x\n", &word) != EOF)
        program_base = word >> 1;
    else {
        printf("Error: Program file is empty\n");
        exit(-1);
    }

    if (is_virtual_base) {
        if (CURRENT_LATCHES.PTBR == 0) {
            printf("Error: Page table base not loaded %s\n", program_filename);
            exit(-1);
        }

        /* convert virtual_base to physical_base */
        virtual_pc = program_base << 1;
        pte = (MEMORY[(CURRENT_LATCHES.PTBR + (((program_base << 1) >> PAGE_NUM_BITS) << 1)) >> 1][1] << 8) |
            MEMORY[(CURRENT_LATCHES.PTBR + (((program_base << 1) >> PAGE_NUM_BITS) << 1)) >> 1][0];

        printf("virtual base of program: %04x\npte: %04x\n", program_base << 1, pte);
        if ((pte & PTE_VALID_MASK) == PTE_VALID_MASK) {
            program_base = (pte & PTE_PFN_MASK) | ((program_base << 1) & PAGE_OFFSET_MASK);
            printf("physical base of program: %x\n\n", program_base);
            program_base = program_base >> 1;
        }
        else {
            printf("attempting to load a program into an invalid (non-resident) page\n\n");
            exit(-1);
        }
    }
    else {
        /* is page table */
        CURRENT_LATCHES.PTBR = program_base << 1;
    }

    ii = 0;
    while (fscanf(prog, "%x\n", &word) != EOF) {
        /* Make sure it fits. */
        if (program_base + ii >= WORDS_IN_MEM) {
            printf("Error: Program file %s is too long to fit in memory. %x\n",
                program_filename, ii);
            exit(-1);
        }

        /* Write the word to memory array. */
        MEMORY[program_base + ii][0] = word & 0x00FF;
        MEMORY[program_base + ii][1] = (word >> 8) & 0x00FF;;
        ii++;
    }

    if (CURRENT_LATCHES.PC == 0 && is_virtual_base)
        CURRENT_LATCHES.PC = virtual_pc;

    printf("Read %d words from program into memory.\n\n", ii);
}

/***************************************************************/
/*                                                             */
/* Procedure : initialize                                      */
/*                                                             */
/* Purpose   : Load microprogram and machine language program  */
/*             and set up initial state of the machine.        */
/*                                                             */
/***************************************************************/
void initialize(char *ucode_filename, char *pagetable_filename, char *program_filename, int num_prog_files) {
    int i;
    init_control_store(ucode_filename);

    init_memory();
    load_program(pagetable_filename, 0);
    for (i = 0; i < num_prog_files; i++) {
        load_program(program_filename, 1);
        while (*program_filename++ != '\0');
    }
    CURRENT_LATCHES.Z = 1;
    CURRENT_LATCHES.STATE_NUMBER = INITIAL_STATE_NUMBER;
    memcpy(CURRENT_LATCHES.MICROINSTRUCTION, CONTROL_STORE[INITIAL_STATE_NUMBER], sizeof(int)*CONTROL_STORE_BITS);
    CURRENT_LATCHES.SSP = 0x3000; /* Initial value of system stack pointer */
    CURRENT_LATCHES.REGS[6] = 0xFE00; /* Initial value of user stack pointer*/

    /* MODIFY: you can add more initialization code HERE */

    NEXT_LATCHES = CURRENT_LATCHES;

    RUN_BIT = TRUE;
}

/***************************************************************/
/*                                                             */
/* Procedure : main                                            */
/*                                                             */
/***************************************************************/
int main(int argc, char *argv[]) {
    FILE * dumpsim_file;

    /* Error Checking */
    if (argc < 4) {
        printf("Error: usage: %s <micro_code_file> <page table file> <program_file_1> <program_file_2> ...\n",
            argv[0]);
        exit(1);
    }

    printf("LC-3b Simulator\n\n");

    initialize(argv[1], argv[2], argv[3], argc - 3);

    if ((dumpsim_file = fopen("dumpsim", "w")) == NULL) {
        printf("Error: Can't open dumpsim file\n");
        exit(-1);
    }

    while (1)
        get_command(dumpsim_file);

}

/***************************************************************/
/* Do not modify the above code.
   You are allowed to use the following global variables in your
   code. These are defined above.

   CONTROL_STORE
   MEMORY
   BUS

   CURRENT_LATCHES
   NEXT_LATCHES

   You may define your own local/global variables and functions.
   You may use the functions to get at the control bits defined
   above.

   Begin your code here 	  			       */
/***************************************************************/


#define MEM_CYCLES_NEW MEM_CYCLES - 2

/*global variables */
int PCMUXout = 0;
int ALUout = 0;
int SHFout = 0;
int MARMUXout = 0;
int MDRout = 0;
int ADDEROut = 0;
int SPMUXout = 0;
int CondCodes = 0;
int MEMORYout = 0;
int MEMORYin = 0;

/*memory cycle counter to keep track of five memory cycles*/
int MEMEN = 0;

/*global access to Register*/
int SR2 = 0;
int SR1 = 0;

int signExtension(int value, int size){
    int result = 0;
    int i = 1;
    int bits = 1;
    int mask = 1;

    /*build the mask according the the bit size*/
    for (i = 1; i < size; i++) {
        bits = bits << 1;
        bits += 1;
    }
    result = (bits & value);
    mask = mask << (size - 1);

    if (mask & result) {
        result += ~bits;
    }

    return result;
}

int processALU(int a, int b, int aluk) {

    int result = 0;

    switch (aluk) {
    case 0:
    {
        result = Low16bits(signExtension(a + b, 16));
        break;
    }
    case 1:
    {
        result = Low16bits(signExtension(a & b, 16));
        break;
    }
    case 2:
    {
        result = Low16bits(signExtension(a ^ b, 16));
        break;
    }
    case 3: {
        result = Low16bits(signExtension(a, 16));
        break;
    }
    }

    return result;
}

int processMUX(int input0, int input1, int input2, int input3,int input4, int select){

    int result = 0;

    switch (select) {
    case 0:
    {
        result = input0;
        break;
    }
    case 1:
    {
        result = input1;
        break;
    }
    case 2:
    {
        result = input2;
        break;
    }
    case 3:
    {
        result = input3;
        break;
    }
	case 4:
	{
		result = input4;
		break;
	}
    }
    return result;
}

int processSHF(int in, int LA_amount) {
    int result = 0;

    int amount = LA_amount & 0x0F;
    int direction = (LA_amount & 0x0030) >> 4;

    switch (direction) {
    case 0: {
        /*logical left shift*/
        result = Low16bits(in << amount);
        break;
    }
    case 1: {
        /*logigal right shift*/
        result = Low16bits(in >> amount);
        break;
    }
    case 3: {
        /*arithmetic right shift*/
        result = Low16bits(signExtension(in, 16) >> amount);
        break;
    }
    }

    return result;
}

void eval_micro_sequencer() {

    /*
     * Evaluate the address of the next state according to the
     * micro sequencer logic. Latch the next microinstruction.
     */
    /*get the required bits for to process the next state*/
    int mio = GetMIO_EN(CURRENT_LATCHES.MICROINSTRUCTION);
    int ird = GetIRD(CURRENT_LATCHES.MICROINSTRUCTION);
    int cond = GetCOND(CURRENT_LATCHES.MICROINSTRUCTION);
    int j = GetJ(CURRENT_LATCHES.MICROINSTRUCTION);
    int r = CURRENT_LATCHES.READY;
    int ben = CURRENT_LATCHES.BEN;
    int instruction = (CURRENT_LATCHES.IR & 0x0000F800) >> 11; /*extract IR[15:11]*/
    int ir_11 = instruction & 0x01;
    int ir_15_12 = (instruction & 0x1E) >> 1;
    int saveNextJ = GetLD_NextJ(CURRENT_LATCHES.MICROINSTRUCTION);

    /*virtual address signals */
    int pte = CURRENT_LATCHES.PTE;
    int valid = (pte & 0x0004) >> 2;
    int pageProteced = (pte & 0x0008) >> 3;
    int A = 0;

    /*interupt variables*/
    int psr_15 = (CURRENT_LATCHES.Priv);
    int INT = 0;
    int protect = 0;
    int prioA = 0;
    int prioB = 0;

    /*use psr or protected pte bit*/
    if ((~pageProteced)&0x0001)
        A = psr_15 & ((~pageProteced)&0x0001);
    else
        A = psr_15;

    /*next state variables*/
    int j0 = 0, j1 = 0, j2 = 0, j3 = 0, j4 = 0, j5 = 0, j6 = 0, nextj = 0;
    int cond0 = cond & 0x01;
    int cond1 = (cond >> 1) & 0x01;
    int cond2 = (cond >> 2) & 0x01;

    /*check protection exception*/
    if ((CURRENT_LATCHES.STATE_NUMBER == 62) ||
        (CURRENT_LATCHES.STATE_NUMBER == 56) ||
        (CURRENT_LATCHES.STATE_NUMBER == 57) ||
        (CURRENT_LATCHES.STATE_NUMBER == 63)) {

        if (CURRENT_LATCHES.MAR < 0x3000 && CURRENT_LATCHES.MAR >= 0x0000 && psr_15 == 1) {
            protect = 1;
        }
        else if (((CURRENT_LATCHES.STATE_NUMBER == 56) ||
            (CURRENT_LATCHES.STATE_NUMBER == 57)) &&
            ((CURRENT_LATCHES.MAR & 0x01) == 1)) {
            nextj = 46;
            goto done;

        }

    }

    /*check for the INT signal*/
    if (INT_SIG == 1 && CURRENT_LATCHES.STATE_NUMBER == 18) {
        prioA = (INT_PRIO & 0x0007);
        prioB = (CURRENT_LATCHES.priority & 0x0007);
        INT = (prioA > prioB) ? 1 : 0;

        /*acknoledge interupt*/
        INT_SIG = 0;
    }

    j0 = j & 0x01;
    j1 = (j >> 1) & 0x01;
    j2 = (j >> 2) & 0x01;
    j3 = (j >> 3) & 0x01;
    j4 = (j >> 4) & 0x01;
    j5 = (j >> 5) & 0x01;
    j6 = (j >> 6) & 0x01;

    /*set next state based on COND, J, and IR[11]*/
    j0 = j0 | (ir_11 & cond0 & cond1 & (~cond2 & 0x01));
    j1 = j1 | (r & cond0 & (~cond1 & 0x01) & (~cond2 & 0x01));
    j2 = j2 | (ben & (~cond0 & 0x01) & cond1 & (~cond2 & 0x01));
    j3 = j3 | (A & (~cond0 & 0x01) & (~cond1 & 0x01) & cond2);
    j4 = j4 | (INT & cond0 & (~cond1 & 0x01) & cond2);
    j5 = j5 | (~valid & cond0 & cond1 & cond2);
    j6 = j6 | (protect & (~cond0 & 0x01) & cond1 & cond2);

    if (saveNextJ) {
        /*save the previous next state before going into tranlate mode*/
        NEXT_LATCHES.NextJ = (j6 << 6) + (j5 << 5) + (j4 << 4) + (j3 << 3) + (j2 << 2) + (j1 << 1) + j0;
    }
    
    /*make sure that we go to interupt service routine instead of translation*/
    if (INT)
        ird = 0;

    if (ird == 0x01) {
        /*set next state based on opcodes*/
        nextj |= ir_15_12;
    }
    else if (ird == 0x02) {
        /*go to the translations states*/
        nextj = 64;
    }
    else if (ird == 0x03) {
        /*return from tranlation states*/
        nextj = CURRENT_LATCHES.NextJ;
    }
    else {
        /*set next sate based on calculated J codes*/
        nextj = (j6 << 6) + (j5 << 5) + (j4 << 4) + (j3 << 3) + (j2 << 2) + (j1 << 1) + j0;
    }

done:
    /*set the next state microinstruction based on the calculated adddress*/
    memcpy(NEXT_LATCHES.MICROINSTRUCTION, CONTROL_STORE[nextj], sizeof(int)*CONTROL_STORE_BITS);
    NEXT_LATCHES.STATE_NUMBER = nextj;

}

void cycle_memory() {

    /*
     * This function emulates memory and the WE logic.
     * Keep track of which cycle of MEMEN we are dealing with.
     * If fourth, we need to latch Ready bit at the end of
     * cycle to prepare microsequencer for the fifth cycle.
     */
    int datasize = GetDATA_SIZE(CURRENT_LATCHES.MICROINSTRUCTION);
    int mio = GetMIO_EN(CURRENT_LATCHES.MICROINSTRUCTION);
    int RW = GetR_W(CURRENT_LATCHES.MICROINSTRUCTION);
    int mar = CURRENT_LATCHES.MAR;
    int mar0 = mar & 0x01;
    int mdr = CURRENT_LATCHES.MDR;

    /*variables*/
    int MAR0MUXout = 0;

    if (mio) {
        /*keep track of how many memory cycles occurred*/
        if (MEMEN < MEM_CYCLES_NEW) {
            MEMEN++;
            NEXT_LATCHES.READY = 0;
        }
        else {
            /*latch the READY bit on the 4th cycle so
            that the microsequencer uses it in the 5th cycle*/
            if (MEMEN == MEM_CYCLES_NEW) {
                MEMEN++;
                NEXT_LATCHES.READY = 1;
            }
            else {
                /*Reset Mem Counter exactly at 5th cycle*/
                MEMEN = 0;
                NEXT_LATCHES.READY = 0;
            }
            /*perform the memory cycle*/
            if (RW) {
                if (datasize == 0) {
                    if (mar0 == 0) {
                        MEMORY[mar / 2][0] = mdr & 0x00FF;
                    }
                    else {
                        MEMORY[mar / 2][1] = (mdr & 0xFF00) >> 8;
                    }
                }
                else {
                    if (mar0 == 0) {
                        MEMORY[mar / 2][0] = 0x00FF & mdr;
                        MEMORY[mar / 2][1] = 0x00FF & ((mdr & 0xFF00) >> 8);
                    }
                }
            }
            else {
                /*place the output of memory ready to load into MDR*/
                MEMORYout = Low16bits(((MEMORY[mar / 2][1] & 0x00FF) << 8) | (MEMORY[mar / 2][0] & 0x00FF));
            }
        }
    }
}

void eval_bus_drivers() {

    /*
     * Datapath routine emulating operations before driving the bus.
     * Evaluate the input of tristate drivers
     *         Gate_MARMUX,
     *		 Gate_PC,
     *		 Gate_ALU,
     *		 Gate_SHF,
     *		 Gate_MDR.
     */
    /*check what are the select lines for the Muxes*/
    int aluk = GetALUK(CURRENT_LATCHES.MICROINSTRUCTION);
    int marmux = GetMARMUX(CURRENT_LATCHES.MICROINSTRUCTION);
    int addr1mux = GetADDR1MUX(CURRENT_LATCHES.MICROINSTRUCTION);
    int addr2mux = GetADDR2MUX(CURRENT_LATCHES.MICROINSTRUCTION);
    int datasize = GetDATA_SIZE(CURRENT_LATCHES.MICROINSTRUCTION);
    int sr1mux = GetSR1MUX(CURRENT_LATCHES.MICROINSTRUCTION);
    int spmux = GetSPMUX(CURRENT_LATCHES.MICROINSTRUCTION);
    int mio = GetMIO_EN(CURRENT_LATCHES.MICROINSTRUCTION);


    /*get load signals*/
    int lshf1 = GetLSHF1(CURRENT_LATCHES.MICROINSTRUCTION);

    /*get stack pointer information*/
    int savssp = CURRENT_LATCHES.SSP;
    int savusp = CURRENT_LATCHES.USP;

    /*get Source register and etc*/
    int Ready = CURRENT_LATCHES.READY;
    int mdr = CURRENT_LATCHES.MDR;
    int mar = CURRENT_LATCHES.MAR;
    int ir = CURRENT_LATCHES.IR;
    int A = (ir & 0x0020) >> 5;
    int SR2MUXout = 0;
    int ADDR1MUXout = 0;
    int ADDR2MUXout = 0;
    int MAR0MUXout = 0;

    /*get the current source registers*/
    SR2 = ir & 0x0007;
    SR1 = processMUX((ir & 0x0E00) >> 9, (ir & 0x01C0) >> 6, 0x06, 0,0, sr1mux);

    /*do nothing while  performing mem cycle*/
    if ((mio == 1) && (CURRENT_LATCHES.READY == 0)) return;

    /*process MDR gate input*/
    MAR0MUXout = processMUX(mdr & 0x00FF, (mdr & 0xFF00) >> 8, 0, 0,0, mar & 0x01);
    MAR0MUXout = Low16bits(signExtension(MAR0MUXout, 8));
    MDRout = processMUX(MAR0MUXout, mdr, 0, 0,0, datasize);


    /*process the MARMUX output*/
    ADDR1MUXout = processMUX(CURRENT_LATCHES.PC, CURRENT_LATCHES.REGS[SR1], 0, 0,0, addr1mux);
    ADDR2MUXout = processMUX(0, signExtension(ir, 6),
        signExtension(ir, 9),
        signExtension(ir, 11),
		0,
        addr2mux);
    if (lshf1)
        ADDR2MUXout = ADDR2MUXout << 1;

    ADDEROut = processALU(ADDR2MUXout, ADDR1MUXout, 0);
    MARMUXout = processMUX((ir & 0xFF) << 1, ADDEROut, 0, 0,0, marmux);

    /*process ALU logic*/
    SR2MUXout = processMUX(CURRENT_LATCHES.REGS[SR2], signExtension(ir, 5), 0, 0,0, A);
    ALUout = processALU(CURRENT_LATCHES.REGS[SR1], SR2MUXout, aluk);

    /*set the Shifter output*/
    SHFout = processSHF(CURRENT_LATCHES.REGS[SR1], ir);

    /*process the Stack pointer MUX output*/
    SPMUXout = processMUX(CURRENT_LATCHES.REGS[SR1] + 2,
        CURRENT_LATCHES.REGS[SR1] - 2,
        CURRENT_LATCHES.SSP,
        CURRENT_LATCHES.USP,
		0,
        spmux);

    /*process PTE address from VA and send it to MAR*/

}


void drive_bus() {

    /*
     * Datapath routine for driving the bus from one of the 5 possible
     * tristate drivers.
     */
    int gatepc = GetGATE_PC(CURRENT_LATCHES.MICROINSTRUCTION);
    int gatepcmin2 = GetGATE_PCmin2(CURRENT_LATCHES.MICROINSTRUCTION);
    int gatealu = GetGATE_ALU(CURRENT_LATCHES.MICROINSTRUCTION);
    int gateshf = GetGATE_SHF(CURRENT_LATCHES.MICROINSTRUCTION);
    int gatemdr = GetGATE_MDR(CURRENT_LATCHES.MICROINSTRUCTION);
    int gatemarmux = GetGATE_MARMUX(CURRENT_LATCHES.MICROINSTRUCTION);
    int gatepsr = GetGATE_PSR(CURRENT_LATCHES.MICROINSTRUCTION);
    int gatesp = GetGATE_SP(CURRENT_LATCHES.MICROINSTRUCTION);
    int gateVec = GetGATE_Vector(CURRENT_LATCHES.MICROINSTRUCTION);
    int mio = GetMIO_EN(CURRENT_LATCHES.MICROINSTRUCTION);
    int gatepte  = GetGATE_PTE(CURRENT_LATCHES.MICROINSTRUCTION);
    int gateptbr = GetGATE_PTBR(CURRENT_LATCHES.MICROINSTRUCTION);
    int gateva   = GetGATE_VA(CURRENT_LATCHES.MICROINSTRUCTION);
    /*only when gateVA and GatePTBR are open*/
    int virtualaddr = gateptbr & gateva & ((~gatepte) & 0x0001);
    /*only when gateVA and GatePTE are open*/
    int physicaladdr = gatepte & gateva & ((~gateptbr) & 0x0001);

    /*PSR variables*/
    int psr, nzp, priority, privilege;
    psr = nzp = priority = privilege = 0;

    /*int virtual address variables*/
    int ptbr, va, pfn;
    ptbr = va = pfn = 0;

    /*do nothing while  performing mem cycle*/
    if ((mio == 1) && (CURRENT_LATCHES.READY == 0)) return;

    /*set the BUS with the current gate that is open*/
    if (gatepc == 1) {
        BUS = CURRENT_LATCHES.PC;
    }
    else if (gatepcmin2 == 1) {
        BUS = CURRENT_LATCHES.PC - 2;
    }
    else if (gatealu == 1) {
        BUS = ALUout;
    }
    else if (gateshf == 1) {
        BUS = SHFout;
    }
    else if (gatemdr == 1) {
        BUS = MDRout;
    }
    else if (gatemarmux == 1) {
        BUS = MARMUXout;
    }
    else if (gatepsr == 1){
        privilege = CURRENT_LATCHES.Priv << 15;
        priority = CURRENT_LATCHES.priority << 8;
        nzp = (CURRENT_LATCHES.N << 2) | (CURRENT_LATCHES.Z << 1) | CURRENT_LATCHES.P;
        psr = privilege | priority | nzp;
        BUS = psr;
    }
    else if (gatesp == 1){
        BUS = SPMUXout;
    }
    else if (gateVec == 1){
        /*The processor left-shifts the interrupt vector one bit, yielding x02,
          and adds it to the base address of the interrupt/exception vector table (x0200),
          yielding the address of the memory location (x0202) that contains the
          starting address of the interrupt service routine.*/
        BUS = Low16bits(0x0200 | ((0x00FF & CURRENT_LATCHES.Vector) << 1));
    }
    else if (virtualaddr){
        /*get the PTE from the virtual address and put it on the bus*/
        ptbr = CURRENT_LATCHES.PTBR & 0xFF00;
        va  = (CURRENT_LATCHES.VA & 0xFE00) >> 9;  /*isolate VA[15:9] into MAR[7:0]*/
        va  = (va & 0x00FF) << 1;                  /*truncate VA to fit exactly [7:0] multiplied by 2*/
        BUS = Low16bits(ptbr | va);                /*get PTE*/
    }
    else if (physicaladdr) {
        /*get the phsyical address from the PTE*/
        pfn = CURRENT_LATCHES.PTE & 0x3E00;
        va  = CURRENT_LATCHES.VA & 0x01FFF;  /*isolate VA[8:0] into MAR[8:0]*/
        BUS = Low16bits(pfn | va);           /*get physical address*/
    }
    else if (gatepte) { /*this line can cause an issue if its before physical address*/
        /*put the full pte into the BUS*/
        BUS = CURRENT_LATCHES.PTE;
    }
    else {
        BUS = 0;
    }
}

void latch_datapath_values() {

    /*
     * Datapath routine for computing all functions that need to latch
     * values in the data path at the end of this cycle.  Some values
     * require sourcing the bus; therefore, this routine has to come
     * after drive_bus.
     */
    /*get the Load signals from the microcode*/
    int ldben = GetLD_BEN(CURRENT_LATCHES.MICROINSTRUCTION);
    int ldcc = GetLD_CC(CURRENT_LATCHES.MICROINSTRUCTION);
    int ldreg = GetLD_REG(CURRENT_LATCHES.MICROINSTRUCTION);
    int ldmar = GetLD_MAR(CURRENT_LATCHES.MICROINSTRUCTION);
    int ldmdr = GetLD_MDR(CURRENT_LATCHES.MICROINSTRUCTION);
    int ldir = GetLD_IR(CURRENT_LATCHES.MICROINSTRUCTION);
    int ldpc = GetLD_PC(CURRENT_LATCHES.MICROINSTRUCTION);
    int ldpriv = GetLD_Priv(CURRENT_LATCHES.MICROINSTRUCTION);
    int ldprio = GetLD_Prio(CURRENT_LATCHES.MICROINSTRUCTION);
    int ldusp = GetLD_SavUSP(CURRENT_LATCHES.MICROINSTRUCTION);
    int ldssp = GetLD_SavSSP(CURRENT_LATCHES.MICROINSTRUCTION);
    int ldvector = GetLD_Vector(CURRENT_LATCHES.MICROINSTRUCTION);
    int drmux = GetDRMUX(CURRENT_LATCHES.MICROINSTRUCTION);
    int datasize = GetDATA_SIZE(CURRENT_LATCHES.MICROINSTRUCTION);
    int mio = GetMIO_EN(CURRENT_LATCHES.MICROINSTRUCTION);
    int pcmux = GetPCMUX(CURRENT_LATCHES.MICROINSTRUCTION);
    int psrmux = GetPSRMUX(CURRENT_LATCHES.MICROINSTRUCTION);
    int vectormux = GetVectorMUX(CURRENT_LATCHES.MICROINSTRUCTION);
    int setpriv = GetSetPriv(CURRENT_LATCHES.MICROINSTRUCTION);
    int ldva = GetLD_VA(CURRENT_LATCHES.MICROINSTRUCTION);
    int ldpte = GetLD_PTE(CURRENT_LATCHES.MICROINSTRUCTION);

    /*Get instruction and etc from the current latches*/
    int condcodes = 0;
    int DRMUXout = 0;
    int MDRBUSout = 0;
    int MAR0MUXout = 0;
    int MIOMUXout = 0;
    int PRIVMUXout = 0;
    int PRIOMUXout = 0;
    int SPMUXout = 0;
    int n = 0, z = 0, p = 0;
    int N = 0, Z = 0, P = 0;
    int ir = CURRENT_LATCHES.IR;

    /*PSR variables*/
    int psr, nzp, priority, privilege;
    psr = nzp = priority = privilege = 0;

    /*do nothing while  performing mem cycle*/
    if ((mio == 1) && (CURRENT_LATCHES.READY == 0)) return;

    if (ldpc) {
        NEXT_LATCHES.PC = processMUX(CURRENT_LATCHES.PC + 2, BUS, ADDEROut, 0,0, pcmux);
    }

    if (ldben) {
        /*get N Z P bits from the current latches*/
        N = CURRENT_LATCHES.N;
        Z = CURRENT_LATCHES.Z;
        P = CURRENT_LATCHES.P;
        /*extract nzp from instruction*/
        n = ir >> 11 & 0x0001;
        z = ir >> 10 & 0x0001;
        p = ir >> 9 & 0x0001;

        if ((n == z) && (z == p))
        {
            /*uncoditional branch*/
            NEXT_LATCHES.BEN = 1;
        }
        else {
            /*condittional branch*/
            NEXT_LATCHES.BEN = (n&N) | (z&Z) | (p&P);
        }
    }

    if (ldcc) {
        /*reset the NZP bits in the latches*/
        NEXT_LATCHES.N = NEXT_LATCHES.Z = NEXT_LATCHES.P = 0;

        if (psrmux) {
            NEXT_LATCHES.N = (BUS & 0x0004) >> 2;
            NEXT_LATCHES.Z = (BUS & 0x0002) >> 1;
            NEXT_LATCHES.P = (BUS & 0x0001);
        }
        else {
            /*get the value on the bus and check for if its - or + or 0*/
            condcodes = signExtension(BUS, 16);
            if (condcodes < 0)
                NEXT_LATCHES.N = 1;
            else if (condcodes == 0)
                NEXT_LATCHES.Z = 1;
            else if (condcodes > 0)
                NEXT_LATCHES.P = 1;
        }
    }

    if (ldreg) {
        /*get the Destination register number (0 to 8)*/
        DRMUXout = processMUX((ir & 0x0E00) >> 9, 0x07, 0x06, 0,0, drmux);

        /*set the destination register with the contents of the BUS*/
        NEXT_LATCHES.REGS[DRMUXout] = Low16bits(BUS);
    }

    if (ldmar) {
        /*set the MAR register with the contents of the bus*/
        NEXT_LATCHES.MAR = BUS;
    }

    if (ldva) {
        /*set virtual address register with the current MAR value*/
        NEXT_LATCHES.VA = Low16bits(CURRENT_LATCHES.MAR);
    }

    if (ldmdr) {
        /*process MDR logic */
        if (datasize == 1)
            MAR0MUXout = processMUX(BUS & 0xFFFF, BUS & 0x00FF, 0, 0,0, CURRENT_LATCHES.MAR & 0x01);
        else
            MAR0MUXout = processMUX(BUS & 0x00FF, (BUS & 0x00FF) << 8, 0, 0,0, CURRENT_LATCHES.MAR & 0x01);

        /*mux the mdr logic with the memory*/
        NEXT_LATCHES.MDR = processMUX(MAR0MUXout, MEMORYout, 0, 0, 0, mio);
    }

    if (ldir) {
        /*set the instruction register with the contents of the BUS*/
        NEXT_LATCHES.IR = BUS;
    }

    if (ldpriv) {
        /*set the privileg lvl of the current program running*/
        PRIVMUXout = processMUX(setpriv, (BUS & 0x7FFF), 0, 0, 0, psrmux);
        NEXT_LATCHES.Priv = PRIVMUXout;
    }

    if (ldprio) {
        /*set the priority register based on the PSR and interupt*/
        PRIOMUXout = processMUX(INT_PRIO & 0x0007, (BUS & 0x0700) >> 8, 0, 0,0, psrmux);
        NEXT_LATCHES.priority = PRIOMUXout;
    }

    if (ldusp) {
        /*set the Source 1 (should be R6) register value into the USP register*/
        NEXT_LATCHES.USP = Low16bits(CURRENT_LATCHES.REGS[SR1]);
    }

    if (ldssp) {
        /*set the Source 1 (should be r6) register value into the SSP register*/
        NEXT_LATCHES.SSP = Low16bits(CURRENT_LATCHES.REGS[SR1]);
    }

    if (ldvector) {
        CURRENT_LATCHES.INTV = 0x01;
        /*load the interupt/exception vector into the vector base register*/
        /*or its a interupt or its an exception*/
        NEXT_LATCHES.Vector = 0x00FF & processMUX(CURRENT_LATCHES.INTV,
											      0x02, 0x03, 0x04,0x05,
												  vectormux);
    }

    if (ldpte){
        /*load our PTE from MDR*/
        if (CURRENT_LATCHES.STATE_NUMBER == 71) {
            NEXT_LATCHES.PTE = CURRENT_LATCHES.PTE | 0x0001; /*set Reference Bit*/
            if ((CURRENT_LATCHES.NextJ == 37) ||
                (CURRENT_LATCHES.NextJ == 47) ||
                (CURRENT_LATCHES.NextJ == 23) ||
                (CURRENT_LATCHES.NextJ == 24))
            {
                /*we are writing so set Modified bit*/
                NEXT_LATCHES.PTE = CURRENT_LATCHES.PTE | 0x0002; /*set Reference Bit*/
            }
        }
        else
            NEXT_LATCHES.PTE = BUS;
    }

    /*always save the state of the PSR whenver
      there is a change on the PSR bits*/
    if (ldpriv || ldprio || ldcc) {
        nzp = (NEXT_LATCHES.N << 2) | (NEXT_LATCHES.Z << 1) | (NEXT_LATCHES.P);
        priority = NEXT_LATCHES.priority << 8;
        privilege = NEXT_LATCHES.Priv << 15;
        psr = privilege | priority | nzp;
        NEXT_LATCHES.PSR = Low16bits(psr);
    }
}
